#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>

#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>

#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_gpio.h>
#include <asm/io.h>
#include <linux/device.h>
#include <linux/irq.h>
#include <linux/of_irq.h>
#include <linux/input.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>

#define DRVNAME "input_deriver"
#define IRQ_NAME "input_irq"
#define InputDevName "input_dev_name"




static int dev_gpio;
static int irq_number;
struct input_dev *input_dev = NULL; //定义按键对应的输入子系统结构体


static irqreturn_t input_irq_hander(int irq, void* dev_id)
{
    int key_status = 0;
    printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
    if (0 == key_status){
        input_report_key(input_dev, KEY_ENTER, 0);
		input_sync(input_dev);
		printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
    }else{
        input_report_key(input_dev, KEY_ENTER, 1);
		input_sync(input_dev);
		printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
    }
	return IRQ_HANDLED;
}

static int input_probe(struct platform_device* pdev)
{
    int err = 0;
    // 获取gpio
	dev_gpio = of_get_named_gpio(pdev->dev.of_node, "gpios", 0);
	if (dev_gpio < 0) {
		printk("can not get dev_gpio! \n");
	}
	printk("dev_gpio =  %d \n", dev_gpio);

	gpio_request(dev_gpio, "dev_gpio");
	gpio_direction_input(dev_gpio);

    //申请中断号、申请中断
	irq_number = gpio_to_irq(dev_gpio);
	printk("the number of irq =  %d \n", irq_number);
	err = request_irq(irq_number, input_irq_hander, IRQF_TRIGGER_FALLING, IRQ_NAME, NULL);

    // 申请输入子系统结构体
    input_dev = input_allocate_device();
    input_dev->name = InputDevName;
    // 设置产生哪类事件
	set_bit(EV_KEY,input_dev->evbit);     //input_dev->evbit[0] = BIT_MASK(EV_KEY);
    // 设置产生哪些事件
	input_set_capability(input_dev, EV_KEY, KEY_ENTER); //标记设备能够触发的事件
    //                    输入子系统结构体 事件类型  事件值

    // 注册输入子系统设备
    err = input_register_device(input_dev);

    return 0;
}

static int input_remove(struct platform_device* dev)
{
	free_irq(irq_number, NULL);
	gpio_free(dev_gpio);
    input_unregister_device(input_dev);
    input_free_device(input_dev);
	return 0;
}


static const struct of_device_id drv_compatible[] = {
	{
	    .compatible = "chengreen_keys",
	},
	{},
};

static struct platform_driver input_drv = {
	.probe = input_probe,
	.remove = input_remove,
	.driver = {
	    .name = DRVNAME,
	    .owner = THIS_MODULE,
	    .of_match_table = drv_compatible,
	},
};


static int __init input_subsys_init(void)
{
	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
	platform_driver_register(&input_drv); // 注册一个平台驱动
	return 0;
}

static void __exit input_subsys_exit(void)
{
	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
	platform_driver_unregister(&input_drv);
}

module_init(input_subsys_init);
module_exit(input_subsys_exit);
MODULE_LICENSE("GPL");







